package com.yuncheng.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CcMinioUtil {
    private static String minioUrl;
    private static String minioName;
    private static String minioPass;
    private static String bucketName;
    private static final Logger log = LoggerFactory.getLogger(CcMinioUtil.class);
    public static void setMinioUrl(String minioUrl) {
        CcMinioUtil.minioUrl = minioUrl;
    }

    public static void setMinioName(String minioName) {
        CcMinioUtil.minioName = minioName;
    }

    public static void setMinioPass(String minioPass) {
        CcMinioUtil.minioPass = minioPass;
    }

    public static void setBucketName(String bucketName) {
        CcMinioUtil.bucketName = bucketName;
    }

    public static String getMinioUrl() {
        return minioUrl;
    }

    public static String getBucketName() {
        return bucketName;
    }

    private static MinioClient minioClient = null;

    /**
     * 上传文件
     */
    public static String upload(String fileName, String fileType,InputStream inputStream, String bizPath, String customBucket) {
        String file_url = "";
        String newBucket = bucketName;
        if(customBucket!=null && !customBucket.equals("")){
            newBucket = customBucket;
        }
        try {
            ccInitMinio(minioUrl, minioName,minioPass);
            // 检查存储桶是否已经存在
            if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
                log.info("Bucket already exists.");
            } else {
                // 创建一个名为ota的存储桶
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
                log.info("create a new bucket.");
            }
//            InputStream stream = file.getInputStream();
            // 获取文件名
//            String orgName = file.getOriginalFilename();
//            orgName = FileUtils.getFileName(orgName);
            int lastPoint = fileName.lastIndexOf(".");
            String preName = fileName;
            String lastName = fileType;
            if(lastPoint != -1){
                preName = fileName.substring(0, lastPoint);
                lastName = fileName.substring(lastPoint);
            }
            String objectName = bizPath+"/"+preName + "_" + System.currentTimeMillis() + lastName;

            // 使用putObject上传一个本地文件到存储桶中。
            try {
                minioClient.putObject(
                        PutObjectArgs.builder().bucket(newBucket).object(objectName).stream(
                                inputStream, inputStream.available(), -1)
                                .contentType("application/octet-stream")
                                .build());
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            file_url = minioUrl+newBucket+"/"+objectName;
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
        return file_url;
    }

    /**
     * 文件上传
     */
    public static String upload(String fileName,String fileType, InputStream inputStream, String bizPath) {
        return  upload(fileName, fileType,inputStream, bizPath,null);
    }

    /**
     * 获取文件流
     * @param bucketName
     * @param objectName
     * @return
     */
    public static InputStream getMinioFile(String bucketName, String objectName){
        InputStream inputStream = null;
        try {
            ccInitMinio(minioUrl, minioName, minioPass);
            GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName)
                    .bucket(bucketName).build();
            inputStream = minioClient.getObject(objectArgs);
        } catch (Exception e) {
            log.info("文件获取失败" + e.getMessage());
        }
        return inputStream;
    }

    /**
     * 获取文件信息
     * @param bucketName
     * @param objectName
     * @return
     */
    public static StatObjectResponse getMinioFileInfo(String bucketName, String objectName){
        try {
            ccInitMinio(minioUrl, minioName, minioPass);
            return minioClient.statObject(StatObjectArgs.builder().object(objectName)
                    .bucket(bucketName).build());
        } catch (Exception e) {
            log.info("文件获取失败" + e.getMessage());
        }
        return null;
    }

    /**
     * 初始化客户端
     * @param minioUrl
     * @param minioName
     * @param minioPass
     * @return
     */

    private static MinioClient ccInitMinio(String minioUrl, String minioName,String minioPass) {
        if (minioClient == null) {
            try {
                minioClient = MinioClient.builder()
                        .endpoint(minioUrl)
                        .credentials(minioName, minioPass)
                        .build();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return minioClient;
    }


    /**
     * 获取文件外链
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param expires    过期时间 <=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .method(Method.GET)
                .expiry(expires)
                .build()
        );
    }

    public static String getObjectName(String url) {
        String str = trimUrl(url);
        if(StrUtil.isBlank(str)) {
            return str;
        }
        return StrUtil.removePrefix(StrUtil.removePrefix(str, bucketName), "/");
    }


    /**
     * 下载文件
     * @param objectName 路径
     * @param response HttpServletResponse
     */
    public static boolean download(String objectName, HttpServletResponse response) {
        initMinio(minioUrl, minioName, minioPass);

        InputStream is = null;
        ServletOutputStream os = null;
        try {
            os = response.getOutputStream();
            is = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
            IoUtil.copy(is, os);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return false;
        } finally {
            IoUtil.close(is);
            IoUtil.close(os);
        }
        return true;
    }


    /**
     * 提取存放路径
     *
     * @param url
     * @return
     */
    public static String trimUrl(String url) {
        if (StrUtil.isBlank(url)) {
            return url;
        }
        StringBuilder sb = new StringBuilder(url);
        int indexAt = sb.indexOf("//");
        if (indexAt > 0){
            sb.delete(0, indexAt + 2);
            indexAt = sb.indexOf("/");
            sb.delete(0, indexAt + 1);
        }
        while (sb.charAt(0) == '/') {
            sb.delete(0, 1);
        }
        return sb.toString();
    }

    public static void removeObject(String url) {
        String newUrl = url.replace(minioUrl, "");
        String newBucket = newUrl.substring(0, newUrl.indexOf("/"));
        String objectName = newUrl.substring(newUrl.indexOf("/") + 1);
        removeObject(newBucket, objectName);
    }

    public static void removeObject(String bucketName, String objectName) {
        try {
            initMinio(minioUrl, minioName, minioPass);
            minioClient.removeObject((RemoveObjectArgs)((io.minio.RemoveObjectArgs.Builder)((io.minio.RemoveObjectArgs.Builder)RemoveObjectArgs.builder().bucket(bucketName)).object(objectName)).build());
        } catch (Exception var3) {
            log.info("文件删除失败" + var3.getMessage());
        }
    }

    private static MinioClient initMinio(String minioUrl, String minioName, String minioPass) {
        if (minioClient == null) {
            minioClient = MinioClient.builder().endpoint(minioUrl).credentials(minioName, minioPass).build();
        }

        return minioClient;
    }

}
